﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Hotfix.Runtime
{
    /// <summary>
    /// 管理Unity生命周期事件的监听与派发
    /// </summary>
    public sealed class UnityLifecycleRegistry : MonoBehaviour
    {
        private static readonly object _lock = new object();

        // 使用只读集合保证线程安全
        private List<Action> _updateListeners = new List<Action>();
        private List<Action> _fixedUpdateListeners = new List<Action>();
        private List<Action> _lateUpdateListeners = new List<Action>();
        private List<Action> _destroyListeners = new List<Action>();
        private List<Action<bool>> _appPauseListeners = new List<Action<bool>>();
        private List<Action<bool>> _appFocusListeners = new List<Action<bool>>();

        private void FixedUpdate() => InvokeListeners(_fixedUpdateListeners);
        private void Update() => InvokeListeners(_updateListeners);
        private void LateUpdate() => InvokeListeners(_lateUpdateListeners);

        private void OnDestroy()
        {
            InvokeListeners(_destroyListeners);
            ClearAllListeners();
        }

        private void OnApplicationFocus(bool hasFocus) => InvokeParamListeners(_appFocusListeners, hasFocus);
        private void OnApplicationPause(bool isPaused) => InvokeParamListeners(_appPauseListeners, isPaused);

        #region 公开接口

        public void AddListener(EventType type, Action action)
        {
            GetListenerList(type).Add(action);
        }

        public void RemoveListener(EventType type, Action action)
        {
            GetListenerList(type).Remove(action);
        }

        public void AddFocusListener(Action<bool> action) => AddParamListener(_appFocusListeners, action);
        public void RemoveFocusListener(Action<bool> action) => RemoveParamListener(_appFocusListeners, action);
        public void AddPauseListener(Action<bool> action) => AddParamListener(_appPauseListeners, action);
        public void RemovePauseListener(Action<bool> action) => RemoveParamListener(_appPauseListeners, action);

        #endregion

        #region 核心实现

        private List<Action> GetListenerList(EventType type)
        {
            return type switch
            {
                EventType.Update => _updateListeners,
                EventType.FixedUpdate => _fixedUpdateListeners,
                EventType.LateUpdate => _lateUpdateListeners,
                EventType.Destroy => _destroyListeners,
                _ => throw new ArgumentOutOfRangeException(nameof(type))
            };
        }

        private void InvokeListeners(List<Action> listeners)
        {
            if (listeners.Count == 0) return;

            Action[] copyArray;
            lock (_lock)
            {
                copyArray = listeners.ToArray();
            }

            foreach (var action in copyArray)
            {
                try
                {
                    action?.Invoke();
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }
        }

        private void InvokeParamListeners(List<Action<bool>> listeners, bool value)
        {
            if (listeners.Count == 0) return;

            Action<bool>[] copyArray;
            lock (_lock)
            {
                copyArray = listeners.ToArray();
            }

            foreach (var action in copyArray)
            {
                try
                {
                    action?.Invoke(value);
                }
                catch (Exception e)
                {
                    Debug.LogException(e);
                }
            }
        }

        private void AddParamListener(List<Action<bool>> list, Action<bool> action)
        {
            lock (_lock)
            {
                if (!list.Contains(action)) list.Add(action);
            }
        }

        private void RemoveParamListener(List<Action<bool>> list, Action<bool> action)
        {
            lock (_lock)
            {
                list.Remove(action);
            }
        }

        private void ClearAllListeners()
        {
            lock (_lock)
            {
                _updateListeners.Clear();
                _fixedUpdateListeners.Clear();
                _lateUpdateListeners.Clear();
                _destroyListeners.Clear();
                _appPauseListeners.Clear();
                _appFocusListeners.Clear();
            }
        }

        #endregion
    }

    /// <summary>
    /// 事件类型枚举
    /// </summary>
    public enum EventType
    {
        Update,
        FixedUpdate,
        LateUpdate,
        Destroy
    }
}